package com.summer.filesync.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/** 文件操作工具类 提供文件相关的通用操作方法 */
public class FileUtils {

  /** 计算文件的MD5校验和 */
  public static String calculateMD5(File file) throws IOException {
    if (!file.exists() || !file.isFile()) {
      throw new IOException("File does not exist or is not a regular file: " + file.getPath());
    }

    try (FileInputStream fis = new FileInputStream(file)) {
      MessageDigest md = MessageDigest.getInstance("MD5");
      byte[] buffer = new byte[8192];
      int bytesRead;

      while ((bytesRead = fis.read(buffer)) != -1) {
        md.update(buffer, 0, bytesRead);
      }

      byte[] digest = md.digest();
      StringBuilder sb = new StringBuilder();
      for (byte b : digest) {
        sb.append(String.format("%02x", b));
      }
      return sb.toString();
    } catch (NoSuchAlgorithmException e) {
      throw new RuntimeException("MD5 algorithm not available", e);
    }
  }

  /** 计算文件的SHA-256哈希值 */
  public static String calculateSHA256(String filePath) throws IOException {
    File file = new File(filePath);
    if (!file.exists() || !file.isFile()) {
      throw new IOException("File does not exist or is not a regular file: " + filePath);
    }

    try (FileInputStream fis = new FileInputStream(file)) {
      MessageDigest md = MessageDigest.getInstance("SHA-256");
      byte[] buffer = new byte[8192];
      int bytesRead;

      while ((bytesRead = fis.read(buffer)) != -1) {
        md.update(buffer, 0, bytesRead);
      }

      byte[] digest = md.digest();
      StringBuilder sb = new StringBuilder();
      for (byte b : digest) {
        sb.append(String.format("%02x", b));
      }
      return sb.toString();
    } catch (NoSuchAlgorithmException e) {
      throw new RuntimeException("SHA-256 algorithm not available", e);
    }
  }

  /** 计算文件校验和（MD5） */
  public static String calculateChecksum(String filePath) throws IOException {
    return calculateMD5(new File(filePath));
  }

  /** 计算字节数组的MD5校验和 */
  public static String calculateMD5(byte[] data) {
    try {
      MessageDigest md = MessageDigest.getInstance("MD5");
      byte[] digest = md.digest(data);
      StringBuilder sb = new StringBuilder();
      for (byte b : digest) {
        sb.append(String.format("%02x", b));
      }
      return sb.toString();
    } catch (NoSuchAlgorithmException e) {
      throw new RuntimeException("MD5 algorithm not available", e);
    }
  }

  /** 复制文件 */
  public static void copyFile(File source, File target) throws IOException {
    Path sourcePath = source.toPath();
    Path targetPath = target.toPath();

    // 确保目标目录存在
    Files.createDirectories(targetPath.getParent());

    Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
  }

  /** 移动文件 */
  public static void moveFile(File source, File target) throws IOException {
    Path sourcePath = source.toPath();
    Path targetPath = target.toPath();

    // 确保目标目录存在
    Files.createDirectories(targetPath.getParent());

    Files.move(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING);
  }

  /** 删除目录及其内容 */
  public static void deleteDirectory(File directory) throws IOException {
    if (!directory.exists()) {
      return;
    }

    if (directory.isDirectory()) {
      File[] files = directory.listFiles();
      if (files != null) {
        for (File file : files) {
          deleteDirectory(file);
        }
      }
    }

    if (!directory.delete()) {
      throw new IOException("Failed to delete: " + directory.getPath());
    }
  }

  /** 获取文件大小（支持大文件） */
  public static long getFileSize(File file) {
    if (!file.exists() || !file.isFile()) {
      return -1;
    }
    return file.length();
  }

  /** 比较两个文件是否相同 */
  public static boolean filesEqual(File file1, File file2) throws IOException {
    if (!file1.exists() || !file2.exists()) {
      return false;
    }

    if (file1.length() != file2.length()) {
      return false;
    }

    String checksum1 = calculateMD5(file1);
    String checksum2 = calculateMD5(file2);

    return checksum1.equals(checksum2);
  }

  /** 创建目录 */
  public static void createDirectories(String path) throws IOException {
    Path dirPath = Paths.get(path);
    Files.createDirectories(dirPath);
  }

  /** 获取文件扩展名 */
  public static String getFileExtension(String fileName) {
    if (fileName == null || fileName.isEmpty()) {
      return "";
    }

    int lastDotIndex = fileName.lastIndexOf('.');
    if (lastDotIndex == -1 || lastDotIndex == fileName.length() - 1) {
      return "";
    }

    return fileName.substring(lastDotIndex + 1);
  }

  /** 标准化路径 */
  public static String normalizePath(String path) {
    if (path == null) {
      return null;
    }

    return Paths.get(path).normalize().toString().replace('\\', '/');
  }

  /** 格式化文件大小 */
  public static String formatFileSize(long size) {
    if (size < 1024) {
      return size + " B";
    } else if (size < 1024 * 1024) {
      return String.format("%.1f KB", size / 1024.0);
    } else if (size < 1024 * 1024 * 1024) {
      return String.format("%.1f MB", size / (1024.0 * 1024));
    } else {
      return String.format("%.1f GB", size / (1024.0 * 1024 * 1024));
    }
  }
}
